home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / gus / guspeak.zip / PHONEME.C < prev    next >
C/C++ Source or Header  |  1993-06-28  |  7KB  |  325 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3.  
  4. #define FALSE (0)
  5. #define TRUE (!0)
  6.  
  7. /*
  8. **    English to Phoneme translation.
  9. **
  10. **    Rules are made up of four parts:
  11. **    
  12. **        The left context.
  13. **        The text to match.
  14. **        The right context.
  15. **        The phonemes to substitute for the matched text.
  16. **
  17. **    Procedure:
  18. **
  19. **        Seperate each block of letters (apostrophes included) 
  20. **        and add a space on each side.  For each unmatched 
  21. **        letter in the word, look through the rules where the 
  22. **        text to match starts with the letter in the word.  If 
  23. **        the text to match is found and the right and left 
  24. **        context patterns also match, output the phonemes for 
  25. **        that rule and skip to the next unmatched letter.
  26. **
  27. **
  28. **    Special Context Symbols:
  29. **
  30. **        #    One or more vowels
  31. **        :    Zero or more consonants
  32. **        ^    One consonant.
  33. **        .    One of B, D, V, G, J, L, M, N, R, W or Z (voiced 
  34. **            consonants)
  35. **        %    One of ER, E, ES, ED, ING, ELY (a suffix)
  36. **            (Right context only)
  37. **        +    One of E, I or Y (a "front" vowel)
  38. */
  39.  
  40. typedef char *Rule[4];    /* A rule is four character pointers */
  41.  
  42. extern Rule *Rules[];    /* An array of pointers to rules */
  43.  
  44. int isvowel(chr)
  45.     char chr;
  46.     {
  47.     return (chr == 'A' || chr == 'E' || chr == 'I' || 
  48.         chr == 'O' || chr == 'U');
  49.     }
  50.  
  51. int isconsonant(chr)
  52.     char chr;
  53.     {
  54.     return (isupper(chr) && !isvowel(chr));
  55.     }
  56.  
  57. xlate_word(word)
  58.     char word[];
  59.     {
  60.     int index;    /* Current position in word */
  61.     int type;    /* First letter of match part */
  62.  
  63.     index = 1;    /* Skip the initial blank */
  64.     do
  65.         {
  66.         if (isupper(word[index]))
  67.             type = word[index] - 'A' + 1;
  68.         else
  69.             type = 0;
  70.  
  71.         index = find_rule(word, index, Rules[type]);
  72.         }
  73.     while (word[index] != '\0');
  74.     }
  75.  
  76. find_rule(word, index, rules)
  77.     char word[];
  78.     int index;
  79.     Rule *rules;
  80.     {
  81.     Rule *rule;
  82.     char *left, *match, *right, *output;
  83.     int remainder;
  84.  
  85.     for (;;)    /* Search for the rule */
  86.         {
  87.         rule = rules++;
  88.         match = (*rule)[1];
  89.  
  90.         if (match == 0)    /* bad symbol! */
  91.             {
  92.             fprintf(stderr,
  93. "Error: Can't find rule for: '%c' in \"%s\"\n", word[index], word);
  94.             return index+1;    /* Skip it! */
  95.             }
  96.  
  97.         for (remainder = index; *match != '\0'; match++, remainder++)
  98.             {
  99.             if (*match != word[remainder])
  100.                 break;
  101.             }
  102.  
  103.         if (*match != '\0')    /* found missmatch */
  104.             continue;
  105. /*
  106. printf("\nWord: \"%s\", Index:%4d, Trying: \"%s/%s/%s\" = \"%s\"\n",
  107.     word, index, (*rule)[0], (*rule)[1], (*rule)[2], (*rule)[3]);
  108. */
  109.         left = (*rule)[0];
  110.         right = (*rule)[2];
  111.  
  112.         if (!leftmatch(left, &word[index-1]))
  113.             continue;
  114. /*
  115. printf("leftmatch(\"%s\",\"...%c\") succeded!\n", left, word[index-1]);
  116. */
  117.         if (!rightmatch(right, &word[remainder]))
  118.             continue;
  119. /*
  120. printf("rightmatch(\"%s\",\"%s\") succeded!\n", right, &word[remainder]);
  121. */
  122.         output = (*rule)[3];
  123. /*
  124. printf("Success: ");
  125. */
  126.         outstring(output);
  127.         return remainder;
  128.         }
  129.     }
  130.  
  131.  
  132. leftmatch(pattern, context)
  133.     char *pattern;    /* first char of pattern to match in text */
  134.     char *context;    /* last char of text to be matched */
  135.     {
  136.     char *pat;
  137.     char *text;
  138.     int count;
  139.  
  140.     if (*pattern == '\0')    /* null string matches any context */
  141.         {
  142.         return TRUE;
  143.         }
  144.  
  145.     /* point to last character in pattern string */
  146.     count = strlen(pattern);
  147.     pat = pattern + (count - 1);
  148.  
  149.     text = context;
  150.  
  151.     for (; count > 0; pat--, count--)
  152.         {
  153.         /* First check for simple text or space */
  154.         if (isalpha(*pat) || *pat == '\'' || *pat == ' ')
  155.             if (*pat != *text)
  156.                 return FALSE;
  157.             else
  158.                 {
  159.                 text--;
  160.                 continue;
  161.                 }
  162.  
  163.         switch (*pat)
  164.             {
  165.         case '#':    /* One or more vowels */
  166.             if (!isvowel(*text))
  167.                 return FALSE;
  168.  
  169.             text--;
  170.  
  171.             while (isvowel(*text))
  172.                 text--;
  173.             break;
  174.  
  175.         case ':':    /* Zero or more consonants */
  176.             while (isconsonant(*text))
  177.                 text--;
  178.             break;
  179.  
  180.         case '^':    /* One consonant */
  181.             if (!isconsonant(*text))
  182.                 return FALSE;
  183.             text--;
  184.             break;
  185.  
  186.         case '.':    /* B, D, V, G, J, L, M, N, R, W, Z */
  187.             if (*text != 'B' && *text != 'D' && *text != 'V'
  188.                && *text != 'G' && *text != 'J' && *text != 'L'
  189.                && *text != 'M' && *text != 'N' && *text != 'R'
  190.                && *text != 'W' && *text != 'Z')
  191.                 return FALSE;
  192.             text--;
  193.             break;
  194.  
  195.         case '+':    /* E, I or Y (front vowel) */
  196.             if (*text != 'E' && *text != 'I' && *text != 'Y')
  197.                 return FALSE;
  198.             text--;
  199.             break;
  200.  
  201.         case '%':
  202.         default:
  203.             fprintf(stderr, "Bad char in left rule: '%c'\n", *pat);
  204.             return FALSE;
  205.             }
  206.         }
  207.  
  208.     return TRUE;
  209.     }
  210.  
  211.  
  212. rightmatch(pattern, context)
  213.     char *pattern;    /* first char of pattern to match in text */
  214.     char *context;    /* last char of text to be matched */
  215.     {
  216.     char *pat;
  217.     char *text;
  218.  
  219.     if (*pattern == '\0')    /* null string matches any context */
  220.         return TRUE;
  221.  
  222.     pat = pattern;
  223.     text = context;
  224.  
  225.     for (pat = pattern; *pat != '\0'; pat++)
  226.         {
  227.         /* First check for simple text or space */
  228.         if (isalpha(*pat) || *pat == '\'' || *pat == ' ')
  229.             if (*pat != *text)
  230.                 return FALSE;
  231.             else
  232.                 {
  233.                 text++;
  234.                 continue;
  235.                 }
  236.  
  237.         switch (*pat)
  238.             {
  239.         case '#':    /* One or more vowels */
  240.             if (!isvowel(*text))
  241.                 return FALSE;
  242.  
  243.             text++;
  244.  
  245.             while (isvowel(*text))
  246.                 text++;
  247.             break;
  248.  
  249.         case ':':    /* Zero or more consonants */
  250.             while (isconsonant(*text))
  251.                 text++;
  252.             break;
  253.  
  254.         case '^':    /* One consonant */
  255.             if (!isconsonant(*text))
  256.                 return FALSE;
  257.             text++;
  258.             break;
  259.  
  260.         case '.':    /* B, D, V, G, J, L, M, N, R, W, Z */
  261.             if (*text != 'B' && *text != 'D' && *text != 'V'
  262.                && *text != 'G' && *text != 'J' && *text != 'L'
  263.                && *text != 'M' && *text != 'N' && *text != 'R'
  264.                && *text != 'W' && *text != 'Z')
  265.                 return FALSE;
  266.             text++;
  267.             break;
  268.  
  269.         case '+':    /* E, I or Y (front vowel) */
  270.             if (*text != 'E' && *text != 'I' && *text != 'Y')
  271.                 return FALSE;
  272.             text++;
  273.             break;
  274.  
  275.         case '%':    /* ER, E, ES, ED, ING, ELY (a suffix) */
  276.             if (*text == 'E')
  277.                 {
  278.                 text++;
  279.                 if (*text == 'L')
  280.                     {
  281.                     text++;
  282.                     if (*text == 'Y')
  283.                         {
  284.                         text++;
  285.                         break;
  286.                         }
  287.                     else
  288.                         {
  289.                         text--; /* Don't gobble L */
  290.                         break;
  291.                         }
  292.                     }
  293.                 else
  294.                 if (*text == 'R' || *text == 'S' 
  295.                    || *text == 'D')
  296.                     text++;
  297.                 break;
  298.                 }
  299.             else
  300.             if (*text == 'I')
  301.                 {
  302.                 text++;
  303.                 if (*text == 'N')
  304.                     {
  305.                     text++;
  306.                     if (*text == 'G')
  307.                         {
  308.                         text++;
  309.                         break;
  310.                         }
  311.                     }
  312.                 return FALSE;
  313.                 }
  314.             else
  315.             return FALSE;
  316.  
  317.         default:
  318.             fprintf(stderr, "Bad char in right rule:'%c'\n", *pat);
  319.             return FALSE;
  320.             }
  321.         }
  322.  
  323.     return TRUE;
  324.     }
  325.